package com.payment.util;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.stereotype.Component;

import java.util.Iterator;
import java.util.Map;
import java.util.Map.Entry;
import java.util.TreeMap;

@Component
public class SignUtil {
	private static final Logger logger = LoggerFactory.getLogger(SignUtil.class);
	protected static String param_signature = ConstantsUtil.getProperty("param_signature");
	protected static String equal = ConstantsUtil.getProperty("equal");
	protected static String ampersand = ConstantsUtil.getProperty("ampersand");
	protected static String cert_log = ConstantsUtil.getProperty("cert_log");
	protected static String cert_path = ConstantsUtil.getProperty("cert_path");
	protected static String cert_pfx = ConstantsUtil.getProperty("cert_pfx");
	protected static String cert_password = ConstantsUtil.getProperty("cert_password");
	protected static String cert_cer = ConstantsUtil.getProperty("cert_cer");
	protected static String bank_dn = ConstantsUtil.getProperty("bank_dn");
	
	static {
		//初始化
		HZBANKSetting hzset = new HZBANKSetting();
		int ret = hzset.initialize(true, cert_log, cert_path, cert_pfx, cert_password, cert_cer, bank_dn); //该代码只需调用一次
		if (ret != 0) { //初始化失败
			logger.info("初始化失败");
		}
	}
	
	public static boolean dataSign(Map<String, Object> data, String encoding) {
		return dataSign(data, encoding, 0);
	}
	
	/**
	 * index 用第几个cert_pfx证书签名
	 */
	public static boolean dataSign(Map<String, Object> data, String encoding, int index) {
		try {
			NetSignServer nss = new NetSignServer();
			if (NetSignServer.isAPIPropertySetted == false) {
				logger.info("签名控件初始化失败");
				return false;
			}
			
			String merchantDN = HZBANKSetting.mcs.get(index).getMerchantCertDN();
			logger.info("签名DN:" + merchantDN);
			// 将Map信息转换成key1=value1&key2=value2的形式
			String sourceMsg = coverMap2String(data);
			logger.info("商户签名原文：" + sourceMsg);
			nss.NSSetPlainText(sourceMsg.getBytes("UTF-8"));
			byte[] bSignMsg = nss.NSDetachedSign(merchantDN);
			if (nss.getLastErrnum() < 0) {
				logger.info("ERROR:商户端签名失败");
				return false;
			}
			String signMsg = new String(bSignMsg, "UTF-8");
			//logger.info("商户签名密文："+signMsg);
			// 设置签名域值
			data.put(param_signature, signMsg);
			logger.info("商户端签名成功：" + nss.getLastErrnum());
			return true;
		} catch (Exception e) {
			logger.info("签名出错：" + e);
			return false;
		}
	}
	
	public static boolean dataSign(Map<String, Object> data, String encoding, String merchantID) {
		int index = 0;
		for (int i = 0; i < HZBANKSetting.mcs.size(); i++) {
			if (HZBANKSetting.mcs.get(i).getMerchantID().equals(merchantID)) {
				index = i;
				break;
			}
		}
		
		return dataSign(data, encoding, index);
	}
	
	/**
	 * index 用第几个cert_pfx证书签名
	 */
	public static String dataSign2(String data, String encoding, int index) {
		try {
			NetSignServer nss = new NetSignServer();
			if (NetSignServer.isAPIPropertySetted == false) {
				logger.info("签名控件初始化失败");
				return "";
			}
			
			String merchantDN = HZBANKSetting.mcs.get(index).getMerchantCertDN();
			logger.info("签名DN:" + merchantDN);
			// 将Map信息转换成key1=value1&key2=value2的形式
			String sourceMsg = data;
			logger.info("商户签名原文：" + sourceMsg);
			nss.NSSetPlainText(sourceMsg.getBytes("UTF-8"));
			byte[] bSignMsg = nss.NSDetachedSign(merchantDN);
			if (nss.getLastErrnum() < 0) {
				logger.info("ERROR:商户端签名失败");
				return "";
			}
			String signMsg = new String(bSignMsg, "UTF-8");
			//logger.info("商户签名密文："+signMsg);
			// 设置签名域值
			logger.info("商户端签名成功：" + nss.getLastErrnum());
			return signMsg;
		} catch (Exception e) {
			logger.info("签名出错：" + e);
			return "";
		}
	}
	
	public static boolean dataVerify(Map<String, Object> data, String encoding) {
		return dataVerify(data, encoding, 0);
	}
	
	/**
	 * index 用第几个bank_dn验签
	 */
	public static boolean dataVerify(Map<String, Object> data, String encoding, int index) {
		String signMsg = (String) (data.remove(param_signature));//签名的密文
		if (null == signMsg || "".equals(signMsg)) {
			logger.info("返回报文签名信息不存在");
			return false;
		}
		
		String srcMsg = coverMap2String(data);//签名的原文
		logger.info("商户验签原文：" + srcMsg);
		//logger.info("商户验签密文："+signMsg);
		
		NetSignServer nss = new NetSignServer();
		if (NetSignServer.isAPIPropertySetted == false) {
			logger.info("签名控件初始化失败");
			return false;
		}
		
		try {
			int veriyCode = -1;
			nss.NSDetachedVerify(signMsg.getBytes("UTF-8"), srcMsg.getBytes("UTF-8"), index);
			veriyCode = nss.getLastErrnum();
			if (veriyCode < 0) { //验签出错
				logger.info("商户端验证签名失败：return code:" + veriyCode);
				return false;
			}
			logger.info("商户端验证签名成功：" + veriyCode);
			return true;
		} catch (Exception e) {
			logger.info("商户端验证异常：" + e);
			return false;
		}
	}
	
	/**
	* index 用第几个bank_dn验签
	*/
	public static boolean dataVerify2(String srcMsg, String signMsg, String encoding, int index) {
		if (null == signMsg || "".equals(signMsg)) {
			logger.info("返回报文签名信息不存在");
			return false;
		}
		
		logger.info("商户验签原文：" + srcMsg);
		//logger.info("商户验签密文："+signMsg);
		
		NetSignServer nss = new NetSignServer();
		if (NetSignServer.isAPIPropertySetted == false) {
			logger.info("签名控件初始化失败");
			return false;
		}
		
		try {
			int veriyCode = -1;
			nss.NSDetachedVerify(signMsg.getBytes("UTF-8"), srcMsg.getBytes("UTF-8"), index);
			veriyCode = nss.getLastErrnum();
			if (veriyCode < 0) { //验签出错
				logger.info("商户端验证签名失败：return code:" + veriyCode);
				return false;
			}
			logger.info("商户端验证签名成功：" + veriyCode);
			return true;
		} catch (Exception e) {
			logger.info("商户端验证异常：" + e);
			return false;
		}
	}
	
	/**
	* 将Map中的数据转换成按照Key的ascii码排序后的key1=value1&key2=value2的形式 不包含签名域signature
	* 
	* @param data
	*            待拼接的Map数据
	* @return 拼接好后的字符串
	*/
	public static String coverMap2String(Map<String, Object> data) {
		TreeMap<String, Object> tree = new TreeMap<String, Object>();
		Iterator<Entry<String, Object>> it = data.entrySet().iterator();
		while (it.hasNext()) {
			Entry<String, Object> en = it.next();
			if (param_signature.equals(en.getKey().trim())) {
				continue;
			}
			tree.put(en.getKey(), en.getValue());
		}
		it = tree.entrySet().iterator();
		StringBuffer sf = new StringBuffer();
		while (it.hasNext()) {
			Entry<String, Object> en = it.next();
			sf.append(en.getKey() + equal + en.getValue() + ampersand);
		}
		return sf.substring(0, sf.length() - 1);
	}
	
	//    public static void main(String[] args) {
	//		Map<String, String> params = new HashMap<String, String>();
	//		params.put("encoding", "UTF-8");
	//		params.put("signMethod", "01");
	//		params.put("sdkAppId", "123");
	//		params.put("certId", "1111");
	//		params.put("txnType", "1000");
	//		params.put("txnSubType", "100000");
	//		params.put("aesWay", "01");
	//		params.put("merId", "8201609250000001");// 本地库商户号
	//		params.put("txnOrderId", (int) (Math.random() * 1000000000) + "");
	//		params.put("txnOrderTime", "20160824155129");
	//		params.put("txnOrderBody", "买毛衣中国");
	//		params.put("txnAmt", "50001");
	//		params.put("txnCcyType", "156");
	//		params.put("frontEndUrl", "http://www.163.com");
	//		params.put("backEndUrl", "http://www.163.com");
	//		params.put("txnProductId", "123131");
	//		params.put("secMerAppId", "wxb44c777cc918d218"); // !!!商户在发起预订单的时候 ,需要上送
	//		
	//		
	//		boolean flag=dataSign(params,"UTF-8");
	//		logger.info(flag);
	//		logger.info(params);
	//		
	//		boolean veryFlag=dataVerify(params,"UTF-8");
	//		logger.info(veryFlag);
	//	}
}
